#include "vc1dec_definitions.h"
#include "vc1stream.h"
#include "vc1mem.h"
#include "vc1vlc.h"


////////This function only supports two stages.
/////more states means less memory space. it need a more general convert function if you want support dranamic stages
I32_VC1 VC1ConvertVLCTable(sVC1VLCCode** table,sVC1VLCCode* codes,U32_VC1 peekBits)
{
	U32_VC1 size,start,end,i,j,tableLen;
	U32_VC1 offset;
	sVC1VLCCode* t = NULL;
	U32_VC1 maxBits = 0;
	if(!codes)
		return -1;

	if(maxBits < peekBits)
		return -1;

	tableLen = (1 << peekBits) + (1 << (maxBits - peekBits));
	t = (sVC1VLCCode*)VC1Malloc(tableLen * sizeof(sVC1VLCCode),4);
	if(!t)
		return -1;

	maxBits = codes[1].len;
	offset = 1 << peekBits;
	
	size = codes[0].code;/////
	for(i = 2; i <= size; i++)
	{
		U32_VC1 bits = codes[i].len;
		if(bits > maxBits)
			maxBits = bits;
	}

	for(i = 1; i <= size; i++)
	{
		I32_VC1 len = codes[i].len;
		I32_VC1 code = codes[i].code;

		if(len <= peekBits)
		{
			I32_VC1 shift = peekBits - len;
			start = code << shift;
			end = start + (1 << shift) - 1;
			for(j = start; j <= end; j++)
			{
				t[j].code = i-1;
				t[j].len = len;
			}
		}
		else
		{
			I32_VC1 secondPeek = maxBits - peekBits;
			I32_VC1 secondLen = len - peekBits;
			I32_VC1 shift = secondPeek - secondLen;
			U32_VC1 secondCode = code & ((1 << secondLen) - 1);
			U32_VC1 baseIndex = code >> secondLen;

			if(secondLen > secondPeek)
				return -1;

			start = secondCode << shift;
			end = start + (1 << shift) - 1;
			t[baseIndex].len = -secondPeek;////negetive number means peek next x bits
			t[baseIndex].code = secondCode;

			for(j = start; j <= end; j++)
			{
				t[j + offset].code = i-1;
				t[j + offset].len = secondLen;
			}
		}
	}

	*table = t;
	return 0;
}


U32_VC1  VC1GetVLC(sVC1Stream* pStream,sVC1VLCCode* table,U32_VC1 peekBits)
{
	U32_VC1 code = VC1ShowBits(pStream,peekBits);
	I32_VC1 bits = table[code].len;

	if(bits < 0)//////peek next
	{
		U32_VC1 secondIndex = 0;
		U32_VC1 offset = 1 << peekBits;
		VC1DumpBits(pStream,peekBits);
		secondIndex = VC1ShowBits(pStream,-bits);
		bits = table[secondIndex + offset].len;
		VC1DumpBits(pStream,bits);
		return table[secondIndex + offset].code;
	}
	else
	{
		VC1DumpBits(pStream,bits);
		return table[code].code;
	}
}